package com.duartepeixinho.P3D.Renderers 
{
	import com.duartepeixinho.P3D.Cameras.Camera;
	import com.duartepeixinho.P3D.Core.Geom.Face3; 
	import com.duartepeixinho.P3D.Objects.DisplayObject3D;
	import com.duartepeixinho.P3D.Objects.Mesh;
	import com.duartepeixinho.P3D.Scenes.Scene;
	import flash.display.Sprite;
	import flash.geom.Point;
	/**
	 * P3D
	 * @version 0.1
	 * @author Duarte Peixinho
	 */
	public class RendererBase extends Sprite
	{
		
		protected var vertices:Array = new Array();
		protected var verticesLength:uint = 0;
		protected var faces:Array = new Array();
		
		public function RendererBase() 
		{
			
		}
		
		protected function updateTriangles(scene:Scene, camera:Camera):void {
			
			vertices = new Array();
			verticesLength = 0;
			faces = new Array();
			
			var MatrixObj:Array = new DisplayObject3D().getObjects;
			
			for (var i:uint = 0; i < MatrixObj.length; i++) {
				
				// update all object matrix, camera matrix and lights
				MatrixObj[i].updateMatrix(camera);
				
			}
			
			// scene objects
			var objects:Array = scene.getChilds();
			for (i = 0; i < objects.length; i++) {
				
				// only renders Mesh
				if (objects[i] is Mesh) {
					
					var o:Mesh = objects[i];				
					o.geometry.updatedVertices = new Array();
					
					// update vertices
					for (var j:uint = 0; j < o.geometry.vertices.length; j++) {
						// apply transformation					
						o.geometry.updatedVertices[j] = o.calcTransform(o.geometry.vertices[j]);
						// copy to renderer's vertices array
						vertices.push(o.geometry.updatedVertices[j]);
					}
					
					// update faces
					for (j = 0; j < o.geometry.faces.length; j++) {
						var face:Face3 = o.geometry.faces[j];
						var f:Face3 = new Face3(o,face.a, face.b, face.c, face.normal, face.material);
						
						// calculate Depth
						f.zDepth(o.geometry.updatedVertices);
						
						// maps face vertex
						f.a += verticesLength;
						f.b += verticesLength;
						f.c += verticesLength;								
						faces.push(f);
					}
					// adds vertices length
					verticesLength += o.geometry.vertices.length;
					o.geometry.calcNormal();
				}
			}
			// sort Z
			faces.sortOn('depth', Array.DESCENDING | Array.NUMERIC);
		}
		
		// backface culling
		protected function triangleIsBackFace(A:Point, B:Point, C:Point):Boolean {
			return (( C.x - A.x ) * ( B.y - A.y ) - ( C.y - A.y ) * ( B.x - A.x ) < 0 );
		}
		
	}

}